"""
主题: 使用延迟计算属性
问题: 你想将一个只读属性定义成一个property，并且只在访问的时候才会计算结果。 但是一旦被访问后，你希望结果值被缓存起来，不用每次都去计算。
提示 : 
"""

import math


class lazyproperty:
    def __init__(self, func):
        self.func = func

    def __get__(self, instance, cls):
        if instance is None:
            return self
        else:
            value = self.func(instance)
            setattr(instance, self.func.__name__, value)
            return value


def lazyproperty2(func):
    name = '_lazy_' + func.__name__
    @property
    def lazy(self):
        if hasattr(self, name):
            return getattr(self, name)
        else:
            value = func(self)
            setattr(self, name, value)
            return value
    return lazy

class Circle:
    def __init__(self, radius):
        self.radius = radius

    @lazyproperty
    def area(self):
        print('Computing area')
        return math.pi * self.radius ** 2

    @lazyproperty2
    def perimeter(self):
        print('Computing perimeter')
        return 2 * math.pi * self.radius

def recipe1():
    c = Circle(4.0)
    print(f"{vars(c) = }")
    print(f"{c.area = }")
    print(f"{vars(c) = }")
    del c.area
    print(f"{vars(c) = }")
    print(f"{c.area = }")
    c.area = 25
    print(f"{c.area = }")

def recipe2():
    c = Circle(4.0)
    print(f"{vars(c) = }")
    print(f"{c.perimeter = }")

    try:
        c.perimeter = 15
    except AttributeError as e:
        print(e)    

def main():
    print('recipe1'.center(20, '*'))
    recipe1()
    print('recipe2'.center(20, '*'))
    recipe2()

if __name__ == '__main__':
    main()           